home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / pascal / SWAG9605.DDD / 0131_Inbound scanning utility.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-05-31  |  14.7 KB  |  432 lines

  1. {
  2. (BTW: it requires a 386 or up to run). It should be
  3. (almost) bug free, since my boss has been running it for about a month by now
  4. and all problems he has found have been fixed.
  5. ------------- BBSCAN.PAS -------------------
  6. }
  7. Program bbscan;
  8.  
  9. {$g+,a+,q-,r-,i-,q-,s-,n-,e-,x+,f-}
  10.  
  11. Uses crt, dos;
  12.  
  13. Const l = 20; {maxlength of areanames, limit of Squish statistics tools}
  14.       maxareas = (65504-2) div (l+1); {around 3000}
  15.  
  16. Type areaarray = Record
  17.                          nofareas: Word;
  18.                          area: Array[0..maxareas] of String[l]
  19.                    End;
  20.  
  21. Const ProgName = 'BackboneScan v1.14, Copyright (c) Gamefreak 1996';
  22.       fs = $64;
  23.       pop_fs = $a10f;
  24.       Fidoexists: Boolean = true;
  25.  
  26. VAR fido, bb, newfido: TEXT;
  27.     areas: ^areaarray;
  28.     c1, c2: Word;
  29.     tempstr: String;
  30.     Asort: Array[0..maxareas] of Word;
  31.  
  32. PROCEDURE Init;
  33. VAR iocheck: Integer;
  34.     f: file;
  35. BEGIN
  36.      ClrScr;
  37.      WRITELN(ProgName);
  38.      WRITELN;
  39.      Assign(f, 'backbone.in');
  40.     {$i-}
  41.      Reset(f);
  42.     {$i+}
  43.      iocheck := ioresult;
  44.      IF iocheck <> 0 THEN
  45.      CASE iocheck OF
  46.           2,3: BEGIN
  47.                WRITELN('File "backbone.in" not found. Please move this program into the right dir');
  48.                WRITELN('and run it again.');
  49.                WRITELN;
  50.                HALT(iocheck)
  51.                END
  52.              ELSE
  53.                BEGIN
  54.                WRITELN('An error (',iocheck,') occurred while opening the file "fidonet.na".');                    WRITELN;
  55.                HALT(iocheck)
  56.                END
  57.      END;
  58.      IF FileSize(f) = 0 THEN
  59.      BEGIN
  60.           WRITELN('Size of file "backbone.in" = 0 bytes. Nothing to do.');
  61.           WRITELN;
  62.           HALT(1)
  63.      END;
  64.      close(f);
  65.      assign(f, 'fidonet.na');
  66.     {$i-}
  67.      reset(f);
  68.     {$i+}
  69.      If ioresult <> 0 Then
  70.         Begin
  71.              rewrite(f);
  72.              fidoexists := false
  73.         End
  74.       Else if filesize(f) = 0 Then fidoexists := false;
  75.      close(f);
  76.      Assign(fido, 'fidonet.na');
  77.      reset(fido);
  78.      Assign(bb, 'backbone.in');
  79.      Reset(bb)
  80. END;
  81.  
  82. PROCEDURE ReadAreaNames;
  83. Var tempstr2: String[12+30];
  84.  
  85. Function Duplicate: Boolean;
  86. Assembler;
  87.         Asm
  88.            cld
  89.            les di, areas
  90.            mov dx, [es:di]      {dx = nofareas}
  91.            xor al, al
  92.            test dx, dx
  93.            jz @end
  94.            add di, 2            {es:di = 1st string}
  95.            xor cx, cx
  96.            mov si, offset tempstr {ds:si points to tempstr}
  97.            mov bl, [si]         {bx = length(tempstr)}
  98.            mov bh, bl
  99.            and bh, 11b          {bh = length(tempstr) mod 4}
  100.            shr bl, 2            {bl = length(tempstr) div 4}
  101.            mov ax, di           {save di in ax}
  102.           @loop:
  103.            mov cl, bl           {cl = length(tempstr) div 4}
  104.            xor ch, ch
  105.            db $66; repe cmpsw   {compare}
  106.            jne @ok              {not equal? -> ok}
  107.            mov cl, bh           {otherwise check remaining bytes}
  108.            repe cmpsb
  109.            je @equal
  110.           @ok:
  111.            mov si, offset tempstr {ds:si points to tempstr}
  112.            add ax, l + 1           {let ax point to next string}
  113.            mov di, ax           {and move it into si}
  114.            dec dx               {decrease the number of areas}
  115.            jnz @loop            {if not zero -> loop}
  116.            xor al, al           {no equal string -> false}
  117.            jmp @end
  118.           @equal:
  119.            mov al, 1            {equal -> true}
  120.           @end:
  121. END;
  122.  
  123. BEGIN
  124.      WRITELN('Reading areanames from "Backbone.in" and removing duplicates...');
  125.      WRITELN;
  126.      IF maxavail < 65535 THEN
  127.         BEGIN
  128.              WRITELN('Not enough memory available.');
  129.              WRITELN;
  130.              close(bb);
  131.              close(fido);
  132.              HALT(8)
  133.         END
  134.          ELSE new(areas);
  135.      fillchar(areas^, sizeof(areas^), 0);
  136.      While (areas^.nofareas < maxareas) and not(eof(bb)) Do
  137.            BEGIN
  138.                 Readln(bb, tempstr);
  139.                 ASM
  140.                    cld                       {this part copies the areaname}
  141.                    push ds                   {to the front of the string}
  142.                    mov di, offset tempstr    {and removes the "xxx messages}
  143.                    mov dx, di                {scanned/tossed" part.}
  144.                    mov si, di
  145.                    add si, 12
  146.                    pop es                    {es:di = sortstr[0]}
  147.                    xor cx, cx
  148.                    mov al, ' '               {used to check length of areaname}
  149.                    mov cl, byte[di]          {cl = length total string}
  150.                    add di, 12                {es:di = sortstr[12]}
  151.                    sub cl, 12
  152.                    mov bx, cx                {save original length - 12}
  153.                    dec bx
  154.                    repne scasb                {scan until a space is encouterd-> eof areaname}
  155.                    sub bx, cx                {calc length of areaname}
  156.                    mov cx, bx                {move length(areaname in cx)}
  157.                    mov di, dx
  158.                    mov [di], cl              {move length of areaname in lengthbyte}
  159.                    inc di                    {points to first char of string}
  160.                    shr cx, 1
  161.                    jnc @even
  162.                    movsb
  163.                   @even:
  164.                    rep movsw                 {move the areaname to the front}
  165.                 END;
  166.                 If not(duplicate) Then
  167.                    With areas^ Do
  168.                         BEGIN
  169.                              area[nofareas] := tempstr;
  170.                              inc(nofareas)
  171.                         END
  172.            END;
  173.            Dec(areas^.nofareas);
  174.            close(bb)
  175. END;
  176.  
  177. Procedure Sort;
  178. Var areasofs: Word;
  179. Begin
  180.      Writeln('Sorting areanames...');
  181.      Writeln;
  182.      Asm
  183.         push ds
  184.         push ds
  185.         dw pop_fs
  186.         cld
  187.         les di, areas
  188.         mov dx, word[es:di]
  189.         mov bx, dx
  190.         add bx, bx
  191.         add bx, offset asort
  192.        @asortinit:
  193.         mov [bx], dx
  194.         sub bx, 2
  195.         dec dx
  196.         jnz @asortinit
  197.         mov dx, [es:di]
  198.         dec dx
  199.         jl @end
  200.         mov ax, dx        {ax = pred(areas^.nofareas)}
  201.         xor dx, dx       
  202.         lds si, areas
  203.         add si, 3
  204.         mov areasofs, si
  205.         xor bx, bx        {bx = c2}
  206.        @outloop:
  207.         mov di, areasofs
  208.         db fs; mov cx, [bx+offset asort+2]
  209.         add di, cx
  210.         shl cx, 2
  211.         add di, cx
  212.         shl cx, 2
  213.         add di, cx
  214.        @loop:
  215.         mov si, areasofs
  216.         db fs; mov cx, [bx+offset asort]
  217.         add si, cx
  218.         shl cx, 2
  219.         add si, cx
  220.         shl cx, 2
  221.         add si, cx
  222.         xor cx, cx
  223.         mov cl, [si-1]
  224.         cmp cl, [di-1]
  225.         jbe @length_ok
  226.         mov cl, [di-1]
  227.        @length_ok:        {cl = length of shortest string}
  228.         push si
  229.         push di
  230.         rep cmpsb         {compare the strings}
  231.         pop si            {si = pushed di and di = pushed si, used so I}
  232.         pop di            {have to recalculate di in the next loop}
  233.         jb @noswitch      {if first < second, don't switch}
  234.         ja @switch        {if first > second, switch}
  235.                           {if the prog gets here, the compared part was equal}
  236.                           {so the longest string is the greatest}
  237.         mov cl, [di-1]    {get length of first string (di has been switched}
  238.                           {with si)}
  239.         cmp cl, [si-1]    {compare with length of second string}
  240.         jbe @noswitch     {length(string 1) < length(string 2) -> no switch}
  241.        @switch:
  242.         mov di, si
  243.         db fs; db $66; ror word[bx+offset asort], 16
  244.        @noswitch:
  245.         sub bx,2          {decrease c2}
  246.         jns @loop         {if above or equal 0 then loop}
  247.         inc dx            {increase c1}
  248.         mov bx, dx        {c2 = c1}
  249.         add bx, bx
  250.         cmp dx, ax        {compare c1 with pred(areas^.nofareas)}
  251.         jbe @outloop      {if below or equal, loop}
  252.        @end:
  253.         pop ds
  254.      End
  255. End;
  256.  
  257. Procedure Update;
  258. Const days : array [0..6] of String[9] =
  259.            ('Sunday','Monday','Tuesday',
  260.             'Wednesday','Thursday','Friday',
  261.             'Saturday');
  262.             areasstillactive: Word = 0;
  263.             areasactivated: Word = 0;
  264.             areasstillnoflow: Word = 0;
  265.             areasnoflow: Word = 0;
  266.             newareascount: Word = 0;
  267.  
  268. Var tempstr2: String;
  269.     logfile: Text;
  270.     dofw, d, m, y: Word;
  271.     h,min,s: String[2];
  272.     Newareas: Array[0..maxareas] of Word;
  273. Begin
  274.      Writeln('Writing new "Fidonet.na"...');
  275.      Writeln;
  276.      Assign(newfido, 'Newfido.na');
  277.      Rewrite(NewFido);
  278.      Assign(logfile, 'bbscan.log');
  279.     {$i-}
  280.      Append(logfile);
  281.     {$i+}
  282.      IF ioresult <> 0 Then Rewrite(logfile);
  283.      If fidoexists Then
  284.        Begin
  285.          Readln(fido,tempstr);
  286.          For c1 := 0 to areas^.nofareas Do
  287.            Begin
  288.               While ((tempstr < areas^.area[asort[c1]]) and not(eof(fido))) Do
  289.                     Begin
  290.                          If length(tempstr) <= l Then
  291.                             Begin
  292.                             Fillchar(tempstr[succ(length(tempstr))], l-length(tempstr), #$20);
  293.                             tempstr[0] :=char(l);
  294.                             tempstr := concat(tempstr, '[FiDo] No description available yet.')
  295.                             End;
  296.                          If tempstr[l+7] = ' ' Then
  297.                             Begin
  298.                                  inc(areasstillnoflow)
  299.                             end
  300.                           Else
  301.                            Begin
  302.                                 inc(areasnoflow);
  303.                                 tempstr[l+7] := ' '
  304.                            End;
  305.                          Writeln(NewFido, tempstr);
  306.                          ReadLn(fido, tempstr)
  307.                     End;
  308.               ASM
  309.                  cld               {This part copies the areaname out of}
  310.                  push ds           {tempstr to tempstr2.}
  311.                  lea di, tempstr
  312.                  pop es
  313.                  mov al, ' '
  314.                  xor bx, bx
  315.                  mov bl, [es:di]
  316.                  cmp bl, l+1
  317.                  ja @length_ok
  318.                  inc bl
  319.                  mov [es:di+bx], al
  320.                 @length_ok:
  321.                  inc di
  322.                  mov cx, l+1
  323.                  mov bx, l
  324.                  repne scasb
  325.                  sub bx, cx
  326.                  push ss
  327.                  mov cx, bx
  328.                  lea si, tempstr+1
  329.                  pop es
  330.                  lea di, tempstr2
  331.                  mov [es:di], cl
  332.                  inc di
  333.                  shr cx, 1
  334.                  jnc @even
  335.                  movsb
  336.                 @even:
  337.                  rep movsw
  338.               END;
  339.               If tempstr2 = areas^.area[asort[c1]] Then
  340.                  Begin
  341.                       If length(tempstr) <= l Then
  342.                          Begin
  343.                               Fillchar(tempstr[succ(length(tempstr))],l-length(tempstr), #$20);
  344.                               tempstr[0] := char(l);
  345.                               tempstr := concat(tempstr, '[FiDo]*No description available yet.')
  346.                               End;
  347.                       If tempstr[l+7] = '*' Then inc(areasstillactive)
  348.                          Else
  349.                              Begin
  350.                                tempstr[l+7] := '*';
  351.                                inc(areasactivated)
  352.                              End;
  353.                       Writeln(NewFido, tempstr);
  354.                       Readln(fido,tempstr)
  355.                  End
  356.                Else
  357.                    Begin
  358.                         newareas[newareascount] := c1;
  359.                         inc(newareascount);
  360.                         tempstr2 := areas^.area[asort[c1]];
  361.                         For c2 := 1 to (l-length(areas^.area[asort[c1]])) Do
  362.                             tempstr2 := concat(tempstr2,' ');
  363.                         tempstr2 := concat(tempstr2, '[FiDo]*New added area. No description available yet.');
  364.                         WriteLn(newfido,tempstr2)
  365.                         End
  366.            End
  367.        End
  368.       Else
  369.          With areas^ Do
  370.           Begin
  371.               For c1 := 0 to nofareas Do
  372.                   Begin
  373.                        tempstr2 := area[asort[c1]];
  374.                        For c2 := 1 to (l-length(area[asort[c1]])) Do
  375.                             tempstr2 := concat(tempstr2,' ');
  376.                         tempstr2 := concat(tempstr2, '[FiDo]*New added area. No description available yet.');
  377.                         WriteLn(newfido,tempstr2)
  378.                         End
  379.        End;
  380.      If fidoexists Then Writeln('"Fidonet.na" has been successfully updated!')
  381.                     Else Writeln('"Fidonet.na" has been successfully created!');
  382.                     Writeln;
  383.      Writeln('Updating logfile (bbscan.log)...');
  384.      Writeln;
  385.      Getdate(y, m, d, dofw);
  386.      Write(logfile,'---------- ',days[dofw],', ', d:0,'/',m:0,'/',y:0,', ');
  387.      Gettime(y, m, d, dofw);
  388.      str(y,h);
  389.      str(m,min);
  390.      str(d,s);
  391.      If length(h) = 1 Then h := concat('0',h);
  392.      If length(min) = 1 Then min := concat('0',min);
  393.      If length(s) = 1 Then s := concat('0',s);
  394.      Writeln(logfile, h,':',min,':',s,'.');
  395.      If (newareascount > 0) Then
  396.              Begin
  397.                   Writeln(logfile, 'New Areas:');
  398.                   For c1 := 0 to pred(newareascount) Do
  399.                       Begin
  400.                            Write(logfile, areas^.area[asort[newareas[c1]]]:38);
  401.                            If (succ(c1) mod 2 = 0) Then Writeln(logfile)
  402.                            End
  403.              End;
  404.      If (succ(c1) mod 2 <> 0) Then Writeln(logfile);
  405.      Writeln(logfile);
  406.      If not(fidoexists) Then newareascount := areas^.nofareas;
  407.      Writeln(logfile, 'Amount of new areas:   ',newareascount);
  408.      Writeln(logfile, 'Areas still active:    ',areasstillactive,'.');
  409.      Writeln(logfile, 'Areas activated:       ',areasactivated,'.');
  410.      Writeln(logfile, 'Areas still down:      ',areasstillnoflow,'.');
  411.      Writeln(logfile, 'Areas deactivated:     ',areasnoflow,'.');
  412.      Writeln(logfile, 'Total number of areas:',newareascount+areasstillactive+areasactivated+areasstillnoflow+areasnoflow,'.');
  413.      Writeln(logfile);
  414.      close(logfile);
  415.      close(newfido);
  416.      close(fido);
  417.     {$i-}
  418.      assign(logfile, 'fidonet.bak');
  419.      Erase(logfile);
  420.      rename(fido, 'fidonet.bak');
  421.      rename(newfido, 'fidonet.na')
  422.     {$i+}
  423. End;
  424.  
  425. Begin
  426.      Init;
  427.      ReadareaNames;
  428.      sort;
  429.      update
  430. END.
  431.  
  432.